package io.renren.sdapi.dto.httprequestparam.image2image;

import io.renren.constant.BizSystemException;
import io.renren.enums.ResultCodeEnum;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class RequestFactory {
    public static <T extends BaseParam> T createRequest(Class<T> requestType, Map<String, Object> map, ExtendedInformation information, Object o) {
        try {
            T request = requestType.getDeclaredConstructor().newInstance();
            if (requestType.equals(RequestTypeEnum.TYPE_A.getAClass())){
                Method method = requestType.getMethod("valueConversion", double.class, Object.class);
                method.invoke(request, information.getDenoising_strength2(), o);
            }
            if (requestType.equals(RequestTypeEnum.TYPE_B.getAClass())){
                Method method = requestType.getMethod("valueConversion", double.class, Object.class);
                method.invoke(request, information.getDenoising_strength2(), o);
            }
            if (requestType.equals(RequestTypeEnum.TYPE_C.getAClass())){
                Method method = requestType.getMethod("valueConversion", Integer.class, Object.class);
                method.invoke(request, information.getDetailingOption(), o);
            }
            if(requestType.equals(RequestTypeEnum.TYPE_D.getAClass())){
                Method method = requestType.getMethod("valueConversion", Object.class);
                method.invoke(request, o);
            }
            if(requestType.equals(RequestTypeEnum.TYPE_E.getAClass())){
                Method method = requestType.getMethod("valueConversion", String.class, double.class, Boolean.class, Integer.class, Object.class);
                method.invoke(request, information.getMask(), information.getDenoising_strength(), information.getInpainting_mask_invert(), information.getInpaint_full_res(), o);
            }
            Map<String, List<Field>> allFields = getAllFields(requestType);
            for(Map.Entry<String, List<Field>> entry : allFields.entrySet()){
                if(entry.getKey().equals(requestType.getName())){
                    continue;
                }
                for(Field field : entry.getValue()){
                    try {
                        field.setAccessible(true);
                        if(field.getType().isArray()){
                            field.set(request, map.get(field.getName()));
                            continue;
                        }
                        if(Map.class.isAssignableFrom(field.getType())){
                            @SuppressWarnings("unchecked")
                            Map<Object, Object> mapValue = (Map<Object, Object>) map.get(field.getName());
                            field.set(request, mapValue);
                            continue;
                        }
                        field.set(request, map.get(field.getName()));
                    } catch (Exception e) {
                        throw new BizSystemException(ResultCodeEnum.CREATE_ENTITY_ERROR.getCode(), ResultCodeEnum.CREATE_ENTITY_ERROR.getMessage());
                    }
                }
            }
            return request;
        } catch (Exception e) {
            throw new BizSystemException(ResultCodeEnum.CREATE_ENTITY_ERROR.getCode(), ResultCodeEnum.CREATE_ENTITY_ERROR.getMessage());
        }
    }

    /**
     * 获取一个类及其所有父类的所有字段（包括私有字段）
     * @param clazz 要检查的类
     * @return 类及其所有父类的所有字段
     */
    public static Map<String, List<Field>> getAllFields(Class<?> clazz) {
        Map<String, List<Field>> fieldsMap = new HashMap<>();
        Class<?> currentClass = clazz;
        // 遍历类的继承树
        while (currentClass != null) {
            // 获取当前类的所有声明字段（包括私有字段）
            Field[] declaredFields = currentClass.getDeclaredFields();
            // 将这些字段添加到列表中
            fieldsMap.put(currentClass.getName(), Arrays.asList(declaredFields));
            // 向上移动到父类
            currentClass = currentClass.getSuperclass();
        }

        // 将列表转换为数组并返回
        return fieldsMap;
    }
}
